#pragma once

#include <windows.h>
#include <map>

/** 
 * \ingroup ti6
 *
 * \brief
 * Dialog is an abstract class which makes it possible to create
 * object-oriented dialog classes. These dialogs can use the class
 * instance while handling messages, without using global variables.
 * An example of a concrete dialog is the MetaDataDialog class.
 *
 * Copyright (c) Academie voor ICT en Media 2007 - 2008
 */
class Dialog
{
public:
	/**
	 \brief
	 Create a dialog instance for the specified resource.
	 
	 \param resource The identifier for the dialog resource, which is
	   a name or identifier obtained by the MAKEINTRESOURCE macro.
	 */
	Dialog( LPWSTR resource );

	/**
	 \brief
	 Destruct the Dialog instance.
	 */
	virtual ~Dialog() {};

	/**
	 \brief
	 Get the window handle for the parent of this dialog.
	 
	 \return The parent window handle.
	 */
	HWND parent() const;

	/**
	 \brief
	 Set the parent for this dialog. This value is valid for all
	 subsequent calls to show().
	 
	 \param parent The handle of the parent.
	 */
	void setParent( HWND parent );

	/**
	 \brief
	 Show the dialog. While the dialog is showed, messages will be sent to
	 handleMessage().
	 
	 \return The return code, as passed by the EndDialog() function. A code
	   of -1 is an error, with the exception of an invalid _hWndParent, which
	   will return 0.
	 */
	virtual UINT_PTR show();

	/**
	 \brief
	 Handle messages, specific for this dialog box. This function will be
	 called when the dialog box is made visible by show().
	 
	 \param uMsg The message id.
	 \param wParam 32 bits value, specific to the message.
	 \param lParam 32 bits value, specific to the message.
	 \return Typically, the function should return TRUE if it processed the
	   message completely, and FALSE if it did not.
	 */
	virtual BOOL handleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) = 0;

	/**
	 \brief
	 Get the window handle for this dialog.
	 
	 \return The window handle.
	 */
	HWND hWnd() const;

private:
	Dialog();

	/**
	 \brief
	 Dispatch Win32 messages to the correct Dialog instance.
	 
	 \param hWndDialog The window handle to the dialog.
	 \param uMsg The message id.
	 \param wParam 32 bits value, specific to the message.
	 \param lParam 32 bits value, specific to the message.
	 \return Typically, the function should return TRUE if it processed the
	   message completely, and FALSE if it did not.
	 */
	static BOOL CALLBACK ooDispatcher(
		HWND hWndDialog,
		UINT uMsg,
		WPARAM wParam,
		LPARAM lParam
		);

	/**
	 \brief
	 Get the Dialog instance for the specified window handle. This
	 instance must have been set previously by setDialogInstance().
	 
	 \param hWndDialog The window handle to the dialog.
	 \return A pointer to the dialog instance, or NULL when the
	   instance is available (never set or already released).
	 */
	static Dialog* dialogInstance( HWND hWndDialog );

	/**
	 \brief
	 Release the dialog instance as set by setDialogInstance(). This
	 function has no effect if hWndDialog is not in the list.
	 
	 \param hWndDialog The window handle to the dialog.
	 */
	static void releaseDialogInstance( HWND hWndDialog );

	/**
	 \brief
	 Set the dialog instance for the given window handle. This handle
	 should be a valid win32 handle to a dialog. The dialog instance
	 can be recalled later on using dialogInstance().
	 
	 \param hWndDialog The window handle to the dialog.
	 \param *instance The Dialog instance.
	 */
	static void setDialogInstance( HWND hWndDialog, Dialog *instance );

	/**
	 An associative array containing Dialog instances by window handles.
	 These values are used to find the correct Dialog instance while
	 dispatching messages.
	 */
	static std::map<HWND,Dialog*> dialogInstanceMap;

	HWND _hWnd, _hWndParent;
	LPWSTR _resource;
};
